#include <iostream>
#include <cstring>
#include <cstdlib>

#include "Perceptron.h"
#include "DataSet.h"
#include "CrossValidation.h"
#include "Defines.h"
#include "CSVFile.h"

void newPerceptron(char *argv[]);
void trainPerceptron(char *argv[]);
void testPerceptron(char *argv[]);
void trainTestPerceptron(char *argv[]);
void infoPerceptron(char *argv[]);
void infoInput(char *argv[]);
void infoOutput(char *argv[]);

int main(int argc, char *argv[])
{
    if(argc == 1)
    {
        cerr << "Usage mode: " << argv[0] << " [create|train|test|train-test|info-perc|info-in|info-out] ..." << endl;
        return EXIT_FAILURE;
    }

    if(!strcmp(argv[1], "create"))
    {
        if(argc != 6)
        {
            cerr << "Usage mode: " << argv[0] << " create <output file> <number of input variables> "
                    "<number of output variables> <learning rate>" << endl;
            return EXIT_FAILURE;
        }

        newPerceptron(argv);
    }

    else if(!strcmp(argv[1], "train"))
    {
        if(argc != 6)
        {
            cerr << "Usage mode: " << argv[0] << " train <perceptron file> <input file> <output file> <maximum number of iterations>" << endl;
            return EXIT_FAILURE;
        }

        trainPerceptron(argv);
    }

    else if(!strcmp(argv[1], "test"))
    {
        if(argc != 5)
        {
            cerr << "Usage mode: " << argv[0] << " test <perceptron file> <input file> <output file>" << endl;
            return EXIT_FAILURE;
        }

        testPerceptron(argv);
    }

    else if(!strcmp(argv[1], "train-test"))
    {
        if(argc != 7)
        {
            cerr << "Usage mode: " << argv[0] << " train-test <perceptron file> <input file> <output file> <number of samples> <maximum number of iterations>" << endl;
            return EXIT_FAILURE;
        }

        trainTestPerceptron(argv);
    }

    else if(!strcmp(argv[1], "info-perc"))
    {
        if(argc != 3)
        {
            cerr << "Usage mode: " << argv[0] << " info-perc <perceptron file>" << endl;
            return EXIT_FAILURE;
        }

        infoPerceptron(argv);
    }

    else if(!strcmp(argv[1], "info-in"))
    {
        if(argc != 3)
        {
            cerr << "Usage mode: " << argv[0] << " info-in <input file>" << endl;
            return EXIT_FAILURE;
        }

        infoInput(argv);
    }

    else if(!strcmp(argv[1], "info-out"))
    {
        if(argc != 3)
        {
            cerr << "Usage mode: " << argv[0] << " info-out <output file>" << endl;
            return EXIT_FAILURE;
        }

        infoOutput(argv);
    }

    else
    {
        cerr << "Usage mode: " << argv[0] << " [create|train|test|train-test|info-perc|info-in|info-out] ..." << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

void newPerceptron(char *argv[])
{
    uint nInVars = atoi(argv[3]);
    uint nOutVars = atoi(argv[4]);
    double learningRate = atof(argv[5]);
    assert(learningRate > 0 && learningRate <= 1);

    Perceptron p(nInVars, nOutVars, learningRate);
    p.saveToFile(argv[2]);
}

void trainPerceptron(char *argv[])
{
    Perceptron p(argv[2]);
    DataSet ds(argv[3], INPUT);
    uint maxIt = atoi(argv[5]);

    p.train(ds, maxIt);
    p.saveToFile(argv[2]);
    ds.saveToFile(argv[4]);
}

void testPerceptron(char *argv[])
{
    Perceptron p(argv[2]);
    DataSet ds(argv[3], INPUT);

    p.test(ds);
    ds.saveToFile(argv[4]);
}

void trainTestPerceptron(char *argv[])
{
    Perceptron p(argv[2]);
    DataSet ds(argv[3], INPUT);
    uint k = atoi(argv[5]);
    uint maxIt = atoi(argv[6]);

    CrossValidation cv(k, ds);
    cv.execute(p, maxIt);

    ds.saveToFile(argv[4]);
}

void infoPerceptron(char *argv[])
{
    Perceptron p(argv[2]);
}

void infoInput(char *argv[])
{
    DataSet ds(argv[2], INPUT);
}

void infoOutput(char *argv[])
{
    DataSet ds(argv[2], OUTPUT);
}

